package com.chj.comp.common.rabbitmq.queue;

import com.chj.comp.common.rabbitmq.sender.MqTopicSender;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 *
 * @Description: 发布订阅模型（Topic主题类型，一个消息被某些消费者消费）：
 * 发送消息时指定路由，交换机会将接收到的消息根据规则路由（模糊匹配）到指定的queue
 *
 *                            / 队列1（模糊绑定路由） - 消费者1
 * 生产者（指定路由） - 交换机
 *                           \ 队列2（模糊绑定路由） - 消费者2
 *
 * topic和direct类似，区别在于routingkey必须是多个单词的列表，并且以 . 分割
 * #：代指0个或多个单词
 * *：代指一个单词
 *
 * @author cuihui
 * @date 2022-06-13
 *
 */
@Configuration
public class MqTopicQueue {
    @Resource
    private RabbitTemplate rabbitTemplate;

    public static final String EXCHANGE_NAME = "mq.topic.exchange";
    public static final String QUEUE_NAME1 = "mq.topic.queue1";
    public static final String ROUTING_KEY1 = "mq.routing.*";
    public static final String QUEUE_NAME2 = "mq.topic.queue2";
    public static final String ROUTING_KEY2 = "mq.#.key";

    /**
     * 定义交换机
     * @return
     */
    @Bean
    public TopicExchange mqTopicExchange() {
        return ExchangeBuilder.topicExchange(EXCHANGE_NAME).build();
    }

    /**
     * 定义队列1
     * @return
     */
    @Bean
    public Queue mqTopicQueue1() {
        return QueueBuilder.durable(QUEUE_NAME1).build();
    }

    /**
     * 定义队列2
     * @return
     */
    @Bean
    public Queue mqTopicQueue2() {
        return QueueBuilder.durable(QUEUE_NAME2).build();
    }

    /**
     * 绑定队列1到交换机
     * @return
     */
    @Bean
    public Binding mqTopicQueue1Binding() {
        return BindingBuilder
                .bind(mqTopicQueue1())
                .to(mqTopicExchange())
                // 队列绑定至交换机并指定路由（模糊匹配）
                .with(ROUTING_KEY1);
    }

    /**
     * 绑定队列2到交换机
     * @return
     */
    @Bean
    public Binding mqTopicQueue2Binding() {
        return BindingBuilder
                .bind(mqTopicQueue2())
                .to(mqTopicExchange())
                // 队列绑定至交换机并指定路由（模糊匹配）
                .with(ROUTING_KEY2);
    }

    @Bean
    public MqTopicSender mqTopicSender() {
        return new MqTopicSender(rabbitTemplate);
    }
}
